package com.edushare.common.util;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


/**
 * Utility class for key based Encryption, decryption using (as of now) AES algorithm.
 * hint: http://java.sun.com/developer/technicalArticles/Security/AES/AES_v1.html
 * 
 * @author Naishe
 * @version 0.0.1-SNAPSHOT
 *
 */
public class CryptionUtil {
	
	private static Log log = LogFactory.getLog(CryptionUtil.class);
	
	//never change this value this crypts the data in table
	private static final String cryptKey = "Mu+0163^#1o?mEn7"; //derived from mutondevelopment
	private static final SecretKeySpec skeySpec = new SecretKeySpec(cryptKey.getBytes(), "AES");
	
	public static String encrypt(String orig) 
	throws IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException
	{
		if(!StringUtil.isValid(orig))
			return orig;
		String encrypted = null;
		/*byte[] raw = cryptKey.getBytes();
		SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");*/
		Cipher cipher = Cipher.getInstance("AES");
		cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
		byte[] encryptedBytes = cipher.doFinal(orig.getBytes());
		encrypted = byteArrayToHexString(encryptedBytes);
		return encrypted;
	}
	
	public static String decrypt(String encryptedHexString) 
	throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException
	{
		if(!StringUtil.isValid(encryptedHexString))
			return encryptedHexString;
		String decryptedValue = null;
		byte[] encryptedBytes = hexStringToByteArray(encryptedHexString);
		Cipher cipher = Cipher.getInstance("AES");
		cipher.init(Cipher.DECRYPT_MODE, skeySpec);
		byte[] decrypted = cipher.doFinal(encryptedBytes);
		decryptedValue = new String(decrypted);
		return decryptedValue;
	}
	
	/**
     * Turns array of bytes into hex string
     *
     * @param buf	Array of bytes to convert to hex string
     * @return	Generated hex string
     */
     private static String byteArrayToHexString (byte buf[]) {
      StringBuffer strbuf = new StringBuffer(buf.length * 2);
      int i;

      for (i = 0; i < buf.length; i++) {
       if (((int) buf[i] & 0xff) < 0x10)
	    strbuf.append("0");

       strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
      }

      return strbuf.toString();
     }
     
     /**
      * Hex values saved as string to byte array
      * @param hexString hexadecimal string
      * @return equivalent byte array
      */
     private static byte[] hexStringToByteArray(String encryptedStr) {
			int arrayLength = encryptedStr.length()/2;
			byte[] inByteFormat = new byte[arrayLength];
			for(int i=0; i<arrayLength; i++){
				inByteFormat[i] = (byte)Integer.parseInt(encryptedStr.substring(i*2, i*2+2), 16);
			}
			return inByteFormat;
	}
     
     /**
      * Test
      * @param str
      * @throws Exception
      */
     public static void main(String[] str) throws Exception{
    	 String input = "Nishant N33raj";
    	 String inc = encrypt(input);
    	 String dec = decrypt(inc);
    	 log.debug("Original: "+input+", Encrypted: "+ inc +", Decrypted: "+dec);
    	 
    	 
     }
}
